<?php
/********************************************************************
 *	Author:
 *		Jestery Liu <jestery@gmail.com>
 *
 *	File:			DB.class.php
 *	Create Date:	2007-05-10 09:54:01 CST
 *******************************************************************/

require_once(PTE::getCoreLibsPath().'DBException.class.php');

abstract class DB
{
	protected $host;
	protected $user;
	protected $passwd;
	protected $dbname;
	protected $charset;
	protected $port;
	protected $socket;
	protected $connected = false;
	protected $inTransaction = false;
	protected $affectedRows = 0;
	protected $numQueries = 0;
	protected $sequenceFormat = "%s_seq";

	const FETCH_ASSOC = 1;
	const FETCH_ARRAY = 2;
	const FETCH_OBJECT = 3;
	const FETCH_NUM = 4;

	const AUTOQUERY_INSERT = 8;
	const AUTOQUERY_UPDATE = 16;

	protected $fetchMode = self::FETCH_ASSOC;
	
	/**
	 * Constructor. This method not really connect to database. You should use the method 'connect' to connect to the database.
	 *
	 * @param string $host The mysql server's hostname.
	 * @param string $user
	 * @param string $passwd
	 * @param string $dbname The database name.
	 * @param string $charset
	 * @param string $port
	 * @param string $socket
	 */
	public function __construct($host, $user, $passwd, $dbname, $charset=NULL, $port=NULL, $socket=NULL)
	{
		$this->host = $host;
		$this->user = $user;
		$this->passwd = $passwd;
		$this->dbname = $dbname;
		$this->charset = $charset;
		$this->port = $port;
		$this->socket = $socket;
	}

	/**
	 * Connect to database.
	 * If the connection has already established, return true directly, else, connect.
	 *
	 * @return true|false
	 */
	public function connect()
	{
	}

	/**
	 * Set the fetch mode when executing fetch
	 *
	 * @param integer $mode one of DB::FETCH_ASSOC, DB::FETCH_ARRAY, DB::FETCH_OBJECT and DB::FETCH_NUM
	 */
	public function setFetchMode($mode)
	{
		$this->fetchMode = $mode;
	}

	/**
	 * Sets the default character set to be used when sending data from and to the database server.
	 *
	 * @param string $charset
	 * @return true|false
	 */
	public function setCharset($charset = null)
	{
	}
	
	/**
	 * Set the format of sequence table's name
	 *
	 * @param string $format The string described in the documentation for sprintf().
	 * @see sprintf();
	 */
	public function setSequenceFormat($format)
	{
		$this->sequenceFormat = $format;
	}

	/**
	 * Turns on or off auto-commiting database modifications
	 *
	 * @param bool $bool Whether to turn on auto-commit or not.
	 * @return true|false
	 */
	public function autoCommit($bool)
	{
	}

	/**
	 * Closes a previously opened database connection
	 *
	 * @return true
	 */
	public function close()
	{
	}

	/**
	 * Starts a transaction.
	 *
	 * @return true|false;
	 */
	public function beginTransaction()
	{
		$this->inTransaction = false;
	}

	/**
	 * Commits the current transaction
	 *
	 * @return true|false;
	 */
	public function commit()
	{
	}

	/**
	 * Rolls back current transaction.
	 *
	 * @return true|false;
	 */
	public function rollBack()
	{
	}

	/**
	 * Escapes special characters in a string for use in a SQL statement.
	 *
	 * @param string $string
	 * @return string
	 */
	public function escape($string)
	{
	}

	/**
	 * Formats input so it can be safely used in a query.
	 *
	 * @param mixed $in
	 * @return mixed The formatted data.
	 */
	public function quote($in)
	{
		if (is_int($in))
		{
			return $in;
		}
		elseif (is_float($in))
		{
			return $this->quoteFloat($in);
		}
		elseif (is_bool($in))
		{
			return $this->quoteBoolean($in);
		}
		elseif (is_null($in))
		{
			return 'NULL';
		}
		else
		{
			return "'".$this->escape($in)."'";
		}
	}

	protected function quoteFloat($float)
	{
		return "'".$this->escape(str_replace(',', '.', strval(floatval($float))))."'";
	}
	
	protected function quoteBoolean($boolean)
	{
		return $boolean ? '1' : '0';
	}

	/**
	 * Prepare a SQL statement for execution.
	 *
	 * @param string $query This parameter can include one or more parameter markers
	 *  in the SQL statement by embedding question mark (?) characters at the appropriate positions.
	 * @return true|false;
	 */
	public function prepare($query)
	{
	}

	/**
	 * Execute a query to the database.
	 *
	 * @param string $query
	 * @return result|false;
	 */
	protected function simpleQuery($query)
	{
	}

	/**
	 * Runs a query.
	 * 
	 * @example <code>
	 * $nickname = 'john';
	 * $address = "NY's somewhere"; // It'll be escaped automatically.
	 * $db = new DB('localhost', 'root', 'password', 'test');
	 * $db->query("INSERT INTO some_table(`nickname`, `address`) VALUES (?,?)", array($nickname, $address));
	 * echo $db->getAffectedRows();
	 * </code>
	 * 
	 * @param string $query SQL query.
	 * @param array $data Quantity of items passed must match quantity of placeholders in the prepared statement.
	 * @return true|false;
	 */
	public function query($query, array $data=array())
	{
	}

	/**
	 * Automatically generates an insert or update query.
	 *
	 * @param string $tableName		The table name.
	 * @param array $fieldsValues	The associative array where key is a field name and value its value.
	 * @param integer $mode			A type of query to make: DB::AUTOQUERY_INSERT or DB::AUTOQUERY_UPDATE
	 * @param string $where			For update queries: the WHERE clause to append to the SQL statement.
	 * 								Don't include the "WHERE" keyword.
	 * 								NOTE: The value in 'WHERE' statement MUST be quouted.
	 * @return true|false
	 * 
	 * @see DB::buildSql(), DB::query()
	 */
	public function autoExecute($tableName, array $fieldsValues, $mode=self::AUTOQUERY_INSERT, $where=false)
	{
	}

	/**
	 * Performs several mysqli_stmt->execute() calls on the prepared statement handle.
	 * 
	 * $allData must be an array indexed numerically from 0,
	 * one execute call is done for every "row" in the array.
	 * 
	 * If an error occurs during execute(), executeMultiple() does not execute the unfinished rows.
	 * 
	 * example:
	 * <code>
	 * $allData = array(array('v1-1', 'v1-2'), array('v2-1','v2-4');
	 * $db->prepare("INSERT INTO some_table('field1', 'field2') values(?,?)");
	 * $db->executeMultiple($allData);
	 * </code>
	 *
	 * @param array $allData Numeric array containing the data to insert into the query.
	 * @return true
	 * 
	 * @see DB::prepare()
	 */
	public function executeMultiple(array $allData)
	{
	}

	/**
	 * Produces an SQL query string.
	 * Example:
	 * <code>
	 * $this->buildSql('some_table', array('f1','f2'));
	 * </code>
	 * That returns:
	 * INSERT INTO some_table (f1, f2) VALUES (?,?)
	 *
	 * @param string $table			The table name.
	 * @param array $tableFields	The array of field names.
	 * @param integer $mode			A type of query to make: self::AUTOQUERY_INSERT or self::AUTOQUERY_UPDATE
	 * @param string $where			For update queries: the WHERE clause to append to the SQL statement.
	 * 								Don't include the "WHERE" keyword.
	 * @return string				The sql query for DB::query or prepare.
	 */
	private function buildSql($table, array $tableFields, $mode, $where = false)
	{
		if (count($tableFields) == 0)
		{
			throw new DBException("Need more data.", DBException::ERROR_QUERYING);
		}
		$first = true;
		switch ($mode) {
			case self::AUTOQUERY_INSERT:
				$values = '';
				$names = '';
				foreach ($tableFields as $value) {
					if ($first)
					{
						$first = false;
					}
					else
					{
						$names .= ',';
						$values .= ',';
					}
					$names .= $value;
					$values .= '?';
				}
				return "INSERT INTO $table ($names) VALUES ($values)";
			case self::AUTOQUERY_UPDATE:
				$set = '';
				foreach ($tableFields as $value) {
					if ($first)
					{
						$first = false;
					}
					else
					{
						$set .= ',';
					}
					$set .= "{$value}=?";
				}
				$sql = "UPDATE {$table} SET {$set}";
				if ($where)
				{
					$sql .= " WHERE {$where}";
				}
				return $sql;
			default:
				throw new DBException('No such mode.', DBException::ERROR_NO_SUCH_MODE);
		}
	}

	/**
	 * Performs a query and get the specified column position's value of first row.
	 *
	 * @param string $query
	 * @param array $data
	 * @return The value that column contians.
	 */
	public function getCol($query, $col=0, array $data=array())
	{
		if ($this->query($query, $data))
		{
			$row = $this->fetch(self::FETCH_NUM);
			if (is_array($row))
			{
				$this->freeResult();
				return $row[$col];
			}
		}
		return false;
	}

	/**
	 * Performs a query and get the value of first row's first column.
	 *
	 * @param string $query
	 * @param array $data
	 * @return The value that column contians.
	 * 
	 * @see DB::getCol()
	 */
	public function getOne($query, array $data=array())
	{
		return $this->getCol($query, 0, $data);
	}

	/**
	 * Performs a query and return all result as an array.
	 *
	 * @param string $query
	 * @param array $data
	 * @return array|false
	 * 
	 * @see DB::fetch(), $DB::query()
	 */
	public function getAll($query, array $data=array())
	{
		$rtn = array();
		if ($this->query($query, $data))
		{
			while ($row = $this->fetch(self::FETCH_ASSOC))
			{
				array_push($rtn, $row);
			}
			$this->freeResult();
			return $rtn;
		}
		return false;
	}
	
	/**
	 * Performs a query and return the first row in result.
	 *
	 * @param string $query
	 * @param array $data
	 * @return array|false
	 */
	public function getRow($query, array $data=array())
	{
		if ($this->query($query, $data))
		{
			$row = $this->fetch(self::FETCH_ARRAY);
			$this->freeResult();
			return $row;
		}
		return false;
	}

	/**
	 * Fetch a result row using a fetchmode.
	 *
	 * @param object $result The query result.
	 * @param integer $mode One of DB::FETCH_ASSOC, DB::FETCH_ARRAY, DB::FETCH_OBJECT, DB::FETCH_NUM. Default is FETCH_ASSOC.
	 * @return array|object
	 * 
	 * @see DB::setFetchMode()
	 */
	public function fetch($mode=null, $result=null)
	{
	}

	/**
	 * Returns number of rows in resultset.
	 *
	 * @return integer
	 */
	public function getNumRows($result=null)
	{
	}

	/**
	 * Returns the auto generated id used in the last query.
	 *
	 * @return integer
	 */
	public function getLastInsertId()
	{
	}

	/**
	 * Gets the number of affected rows in the last query.
	 *
	 * @return integer
	 */
	public function getAffectedRows()
	{
		return $this->affectedRows;
	}

	/**
	 * Gets the total queries.
	 *
	 * @return integer
	 */
	public function getNumQueries()
	{
		return $this->numQueries;
	}
	/**
	 * Gets the string that describes the last error message of mysqli or mysqli_stmt object.
	 *
	 * @return string If no error occurred, returns an empty string.
	 */
	public function getErrorMessage()
	{
	}

	/**
	 * Returns the next free id in a sequence.
	 *
	 * @param string $seqName Name of the sequence.
	 * @return integer The next id number in the sequence.
	 * 
	 * @see DB::getSeqTableName(), DB::createSeqTable()
	 */
	public function nextId($seqName)
	{
	}

	/**
	 * Generates the name used inside the database for a sequence.
	 *
	 * @param string $name The sequence's public name.
	 * @return string The sequence table name in the backend.
	 */
	protected function getSeqTableName($name)
	{
		return sprintf($this->sequenceFormat, $name);
	}

	/**
	 * Creates a new sequence table.
	 *
	 * @param string $tableName Name of the new sequence table.
	 * @return true|false
	 */
	protected function createSeqTable($tableName)
	{
	}

	/**
	 * Check if a table exists.
	 *
	 * @param string $tableName The table's name which you want to check.
	 * @return true|false
	 */
	public function tableExists($tableName)
	{
	}

	/**
	 * frees result memory
	 *
	 */
	public function freeResult()
	{
	}
	
		
	/**
     * Tell whether a query is a data manipulation or data definition query
     *
     * Examples of data manipulation queries are INSERT, UPDATE and DELETE.
     * Examples of data definition queries are CREATE, DROP, ALTER, GRANT,
     * REVOKE.
     * 
     * From PEAR::DB
     *
     * @param string $query the query
     *
     * @return boolean  whether $query is a data manipulation query
     */
    protected function isManip($query)
    {
        $manips = 'INSERT|UPDATE|DELETE|REPLACE|'
                . 'CREATE|DROP|'
                . 'LOAD DATA|SELECT .* INTO .* FROM|COPY|'
                . 'ALTER|GRANT|REVOKE|'
                . 'LOCK|UNLOCK';
        if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) {
            return true;
        }
        return false;
    }

	public function __destruct()
	{
	}
}